package com.ming.mallchat.common.chat.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.ming.mallchat.common.chat.cache.RoomCache;
import com.ming.mallchat.common.chat.cache.RoomGroupCache;
import com.ming.mallchat.common.chat.dao.GroupMemberDao;
import com.ming.mallchat.common.chat.dao.MessageDao;
import com.ming.mallchat.common.chat.dao.MessageMarkDao;
import com.ming.mallchat.common.chat.dao.RoomFriendDao;
import com.ming.mallchat.common.chat.domain.vo.req.ChatMessageReq;
import com.ming.mallchat.common.chat.domain.vo.resp.ChatMessageResp;
import com.ming.mallchat.common.chat.pojo.*;
import com.ming.mallchat.common.chat.service.ChatService;
import com.ming.mallchat.common.chat.service.adapter.MessageAdapter;
import com.ming.mallchat.common.chat.service.strategy.msg.AbstractMsgHandler;
import com.ming.mallchat.common.chat.service.strategy.msg.MsgHandlerFactory;
import com.ming.mallchat.common.common.domain.enums.NormalOrNoEnum;
import com.ming.mallchat.common.common.event.MessageSendEvent;
import com.ming.mallchat.common.common.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 86150
 * @date 2023/10/12
 */
@Service
public class ChatServiceImpl implements ChatService {

    @Autowired
    private MessageDao messageDao;
    @Autowired
    private RoomCache roomCache;
    @Autowired
    private RoomFriendDao roomFriendDao;
    @Autowired
    private RoomGroupCache roomGroupCache;
    @Autowired
    private GroupMemberDao groupMemberDao;
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;
    @Autowired
    private MessageMarkDao messageMarkDao;

    /**
     * 发送消息
     *
     * @param request
     * @param uid
     * @return {@link Long}
     */
    @Override
    public Long sendMsg(ChatMessageReq request, Long uid) {
        check(request, uid);
        AbstractMsgHandler msgHandler = MsgHandlerFactory.getStrategyNoNull(request.getMsgType());
        Long msgId = msgHandler.checkAndSaveMsg(request, uid);
        applicationEventPublisher.publishEvent(new MessageSendEvent(this, msgId));
        return msgId;
    }

    private void check(ChatMessageReq request, Long uid) {
        Room room = roomCache.get(request.getRoomId());
        if (room.isHotRoom()) {//全员群跳过校验
            return;
        }
        if (room.isRoomFriend()) {
            RoomFriend roomFriend = roomFriendDao.getRoomId(request.getRoomId());
            AssertUtil.equal(roomFriend.getStatus(), NormalOrNoEnum.NORMAL.getStatus(),"您已经被对方拉黑了");
            AssertUtil.isTrue(uid.equals(roomFriend.getUid1()) || uid.equals(roomFriend.getUid2()), "您已经被对方拉黑");
        }
        if (room.isRoomGroup()) {
            RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
            GroupMember member = groupMemberDao.getMember(roomGroup.getId(), uid);
            AssertUtil.isNotEmpty(member, "您已经被移除该群");
        }
    }

    @Override
    public ChatMessageResp getMsgResp(Message message, Long receiveUid) {
        return CollUtil.getFirst(getMsgRespBatch(Collections.singletonList(message), receiveUid));
    }

    /**
     * @param msgId
     * @param uid
     * @return {@link ChatMessageResp}
     */
    @Override
    public ChatMessageResp getMsgResp(Long msgId, Long uid) {
        Message message = messageDao.getById(msgId);
        return getMsgResp(message,uid);
    }

    private List<ChatMessageResp> getMsgRespBatch(List<Message> messages, Long receiveUid) {
        if (CollectionUtil.isEmpty(messages)) {
            return new ArrayList<>();
        }
        Map<Long, Message> replyMap = new HashMap<>();
        //批量查出回复的消息
        List<Long> replyIds = messages.stream().map(Message::getReplyMsgId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(replyIds)) {
            replyMap = messageDao.listByIds(replyIds).stream().collect(Collectors.toMap(Message::getId, Function.identity()));
        }
        //查询消息标志
        List<MessageMark> msgMark = messageMarkDao.getValidMarkByMsgIdBatch(messages.stream().map(Message::getId).collect(Collectors.toList()));
        return MessageAdapter.buildMsgResp(messages, replyMap, msgMark, receiveUid);
    }
}
